////////////////////////////////////////////////////////////////////
// Programme de dump de donnees depuis des fichiers de Chrono Cross
////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////
// Nemesis pour Terminus Traduction (tt_nemesis@yahoo.fr)
// Date de création :		04/09/03
// Dernière modification :	05/09/03
////////////////////////////////////////////////////////////////////

// Entete
#include "Brut.h"

// Type de données pour les fichiers
typedef struct {
	char *nom;
	_int32 adr_deb;
	_int32 adr_fin;
} Brt_TFich;

// Informations sur les fichiers
Brt_TFich Brt_Outs[BRT_FICHS_NB];
_int16 Brt_Outs_Nb;

/*------------------------------------------------------------------
  Initialisation des fichiers bruts
--------------------------------------------------------------------
 <- dir : chemin partiel des infos à charger
 <- fich : fichier d'infos à charger
------------------------------------------------------------------*/
void Brt_Infos (char *dir, char *fich)
{
	// Fichier des infos
	FILE *infos_f;
	// Nom de l'iso (chemin)
	char infos_nom[BRT_NOM_MAX];
	// Numero de fichier
	int fich_deb,fich_fin;
	// Nom de fichier
	char fich_nom_complet[BRT_FICHS_NOM];
	char fich_nom[BRT_FICHS_NOM];
	char fich_ext[4];
	// Ligne
	char ligne[BRT_LIGNE_MAX];
	// Nombre de champs d'infos
	int result;

	// Ouverture du fichier des infos principales
	sprintf(infos_nom,"%s%s%s%s.%s",
		DIR_INFOS,DIR_INFOS_BRT,dir,fich,EXT_INFOS);
	infos_f=fopen(infos_nom,"rb");

	if (infos_f==NULL)
		Main_Message_S("Erreur d'ouverture des infos.\n","",ER);
	else {
		// Réinitialisation
		Brt_Outs_Nb=0;
		// Récupération des noms de fichiers
		while (fgets(ligne,BRT_LIGNE_MAX,infos_f)!=NULL)
			// Cas d'un commentaire ou d'un blanc
			if (ligne[0]!=COMMENT) {
				result=sscanf(ligne,"%d-%d %3s %s",
					&fich_deb,&fich_fin,fich_ext,fich_nom);
				switch (result) {
				case 4:
					sprintf(fich_nom_complet,
						" (%s).%s",fich_nom,fich_ext);
					Brt_Outs[Brt_Outs_Nb].adr_deb=fich_deb;
					Brt_Outs[Brt_Outs_Nb].adr_fin=fich_fin;
					Brt_Outs[Brt_Outs_Nb].nom=strdup(fich_nom_complet);
					Brt_Outs_Nb++;
					break;
				default:
					Main_Message_S("Info erronee... ","",ER);
				}
			}
		// Fermeture du fichier des infos
		fclose(infos_f);
	}
}

/*------------------------------------------------------------------
  Réinitialisation des informations à NULL
------------------------------------------------------------------*/
void Brt_Infos_Vide (void)
{
	int f;

	for(f=0;f<BRT_FICHS_NB;f++)
		if (Brt_Outs[f].nom!=NULL) {
			free(Brt_Outs[f].nom);
			Brt_Outs[f].nom=NULL;
		}
}

/*------------------------------------------------------------------
  Extraction de données brutes d'un fichier
--------------------------------------------------------------------
 <- dir : dossier du fichier à traiter
 <- fich : fichier d'où extraire les fichiers (sans extension)
------------------------------------------------------------------*/
void Brt_Dump (char* fich)
{
	// Dossier/fichiers
	char* dir;
	char* fichier;
	// Fichier de donnees
	FILE *brt_f;
	char brt_nom[BRT_NOM_MAX];
	char *brt_nom2;
	char brt_nom_complet[BRT_NOM_MAX];
	// Fichier de sortie
	FILE *out_f;
	char out_nom[BRT_NOM_MAX];
	// Nom du dossier
	char dossier[BRT_NOM_MAX];
	// Index des fichiers
	int f;
	// Position d'arrêt de copie
	_int32 pos;
	// Buffer
	char buffer[BRT_BUFFER];

	Main_Message_S("Extraction de donnees de %s... ",fich,OK);

	// Décomposition dossier/fichiers
	dir=strtok(fich,SEPARATEUR);
	if (dir[0]==NEUTRE)
		dir[0]=0;
	fichier=strtok(NULL,SEPARATEUR);

	// Recherche du fichier de données brutes
	sprintf(brt_nom,"%04d",atoi(fichier));
	sprintf(dossier,"%s%s",DIR_FICH_IN,dir);
	Fichier_Cherche(dossier,brt_nom,EXT_BRT,&brt_nom2);
	sprintf(brt_nom_complet,"%s%s",dossier,brt_nom2);
	// Ouverture du fichier BRT
	brt_f=fopen(brt_nom_complet,"rb");

	// Fichier existant ?
	if (brt_f==NULL)
		Main_Message_S("Impossible d'ouvrir le fichier.\n","",ER);
	else {
		// Chargement des paramètres d'extraction
		Brt_Infos(dir,brt_nom);
		// Creation du dossier (s'il n'existe pas déjà)
		sprintf(dossier,"%s%s%s%s\\",
			DIR_FICH_IN,dir,ENT_DOSSIER,brt_nom);
		mkdir(dossier);
		// Extraction des fichiers
		for(f=0;f<Brt_Outs_Nb;f++) {
			// Ouverture du fichier extrait
			sprintf(out_nom,"%s%04d%s",dossier,f,Brt_Outs[f].nom);
			out_f=fopen(out_nom,"wb");
			if (out_f==NULL)
				Main_Message_S("Impossible d'extraire.\n","",ER);
			else {
				// Placement dans le fichier
				fseek(brt_f,Brt_Outs[f].adr_deb,SEEK_SET);
				// Extraction du fichier
				for(pos=Brt_Outs[f].adr_deb;
					pos<Brt_Outs[f].adr_fin-BRT_BUFFER;
					pos+=BRT_BUFFER)
				{
					fread(buffer,sizeof(char),BRT_BUFFER,brt_f);
					fwrite(&buffer,sizeof(char),BRT_BUFFER,out_f);
				}
				// Attention à l'ordre pour
				// rester dans les positifs
				pos=(Brt_Outs[f].adr_fin
					-Brt_Outs[f].adr_deb)%BRT_BUFFER;
				fread(buffer,sizeof(char),pos,brt_f);
				fwrite(&buffer,sizeof(char),pos,out_f);
				// Fermeture du fichier extrait
				fclose(out_f);
			}
		}
		// Fermeture du fichier de données
		fclose(brt_f);
		// Nettoyage des infos brt
		Brt_Infos_Vide();
	}

	Main_OK();
}

/*------------------------------------------------------------------
  Réinsertion de données brutes dans un fichier
--------------------------------------------------------------------
 <- dir : dossier du fichier où réinsérer
 <- fich : fichier où réinsérer (sans extension pour dossier)
------------------------------------------------------------------*/
void Brt_Rein (char *fich)
{
	// Dossier/fichiers
	char* dir;
	char* fichier;
	// Fichier de donnees
	FILE *brt_f;
	char brt_nom[BRT_NOM_MAX];
	char *brt_nom2;
	char brt_nom_complet[BRT_NOM_MAX];
	// Fichier à réinsérer
	FILE *in_f;
	char in_nom[BRT_NOM_MAX];
	// Nom du dossier
	char dossier_in[BRT_NOM_MAX];
	char dossier[BRT_NOM_MAX];
	// Index des fichiers
	int f;
	// Position d'arrêt de copie
	_int32 pos;
	// Buffer
	char buffer[BRT_BUFFER];
	int nb_car;

	Main_Message_S("Reinsertion de donnees dans %s... ",fich,OK);

	// Décomposition dossier/fichiers
	dir=strtok(fich,SEPARATEUR);
	if (dir[0]==NEUTRE)
		dir[0]=0;
	fichier=strtok(NULL,SEPARATEUR);

	// Copie du fichier de données brutes
	sprintf(dossier_in,"%s%s",DIR_FICH_IN,dir);
	sprintf(dossier,"%s%s",DIR_FICH_OUT,dir);
	Fichier_Copie(atoi(fichier),dossier_in,dossier,EXT_BRT);

	// Recherche du fichier de données brutes
	sprintf(brt_nom,"%04d",atoi(fichier));
	sprintf(dossier,"%s%s",DIR_FICH_OUT,dir);
	Fichier_Cherche(dossier,brt_nom,EXT_BRT,&brt_nom2);
	sprintf(brt_nom_complet,"%s%s",dossier,brt_nom2);
	// Ouverture du fichier de données
	brt_f=fopen(brt_nom_complet,"r+b");

	// Fichier existant ?
	if (brt_f==NULL)
		Main_Message_S("Impossible d'ouvrir le fichier.\n","",ER);
	else {
		// Chargement des paramètres d'extraction
		Brt_Infos(dir,brt_nom);
		// Dossier des fichiers extraits
		sprintf(dossier,"%s%s%s%s\\",
			DIR_FICH_OUT,dir,ENT_DOSSIER,brt_nom);
		// Extraction des fichiers
		for(f=0;f<Brt_Outs_Nb;f++) {
			// Ouverture du fichier extrait
			sprintf(in_nom,"%s%04d%s",dossier,f,Brt_Outs[f].nom);
			in_f=fopen(in_nom,"rb");
			if (in_f==NULL)
				Main_Message_S("Impossible d'inserer.\n","",ER);
			else {
				// Placement dans le fichier
				fseek(brt_f,Brt_Outs[f].adr_deb,SEEK_SET);
				// Réinsertion du fichier
				nb_car=fread(buffer,sizeof(char),BRT_BUFFER,in_f);
				while(ftell(brt_f)+nb_car<=Brt_Outs[f].adr_fin && nb_car>0) {
					fwrite(&buffer,sizeof(char),nb_car,brt_f);
					nb_car=fread(buffer,sizeof(char),BRT_BUFFER,in_f);
				}
				// Test de débordement
				if (nb_car>0) {
					ftell(brt_f);
					Main_Message_S("Debordement dans %s.\n",fichier,ER);
				}
				else {
					while (ftell(brt_f)<Brt_Outs[f].adr_fin) {
						fputc(0,brt_f);
						pos++;
					}
				}
				// Fermeture du fichier extrait
				fclose(in_f);
			}
		}
		// Fermeture du fichier de données
		fclose(brt_f);
		// Nettoyage des infos brt
		Brt_Infos_Vide();
	}

	Main_OK();
}